package ui

import (
	"gioui.org/layout"
	"gioui.org/op/clip"
	"gioui.org/op/paint"
	"gioui.org/unit"
	"gioui.org/widget"
	"gioui.org/widget/material"
	"image"
	"image/color"
)

type DialogType int

const (
	Info DialogType = iota
	Success
	Warning
	Error
	Confirm
)

type Dialog struct {
	Type    DialogType
	Title   string
	Message string

	// 按钮回调
	OnConfirm func()
	OnCancel  func()

	// 确认/取消按钮文本
	ConfirmText string
	CancelText  string

	// 是否可见
	Visible bool
	// 按钮可见
	ConfirmVisible bool
	CancelVisible  bool

	// “确定”按钮
	confirmBtn widget.Clickable
	// “取消”按钮（仅 Confirm 类型）
	cancelBtn widget.Clickable

	th        *material.Theme
	titleTh   *material.Theme
	messageTh *material.Theme
}

func NewDialog(th *material.Theme) *Dialog {
	return &Dialog{
		ConfirmText:    "确定",
		CancelText:     "取消",
		th:             th,
		titleTh:        th,
		messageTh:      th,
		ConfirmVisible: true,
		CancelVisible:  true,
	}
}

func (d *Dialog) ShowInfo(title, message string) {
	d.Visible = true
	d.Title = title
	d.Message = message
	d.Type = Info

	d.titleTh = d.th
	d.messageTh = d.th
}

func (d *Dialog) ShowSuccess(title, message string) {
	d.Visible = true
	d.Title = title
	d.Message = message
	d.Type = Success

	d.titleTh = material.NewTheme()
	d.messageTh = d.titleTh
	d.titleTh.Fg = color.NRGBA{G: 255, A: 255}
}

func (d *Dialog) ShowWarn(title, message string) {
	d.Visible = true
	d.Title = title
	d.Message = message
	d.Type = Warning

	d.titleTh = material.NewTheme()
	d.messageTh = d.titleTh
	d.titleTh.Fg = color.NRGBA{R: 255, G: 255, A: 255}
}

func (d *Dialog) ShowError(title, message string) {
	d.Visible = true
	d.Title = title
	d.Message = message
	d.Type = Error

	d.titleTh = material.NewTheme()
	d.messageTh = d.titleTh
	d.titleTh.Fg = color.NRGBA{R: 255, A: 255}
}

func (d *Dialog) ShowConfirm(title, message string) {
	d.Visible = true
	d.Title = title
	d.Message = message
	d.Type = Confirm

	d.titleTh = d.th
	d.messageTh = d.th
}

func (d *Dialog) Show()           { d.Visible = true }
func (d *Dialog) Dismiss()        { d.Visible = false }
func (d *Dialog) IsVisible() bool { return d.Visible }

func (d *Dialog) Layout(gtx layout.Context) layout.Dimensions {
	if d.confirmBtn.Clicked(gtx) {
		d.Visible = false

		if d.OnConfirm != nil {
			d.OnConfirm()
		}
	}

	if d.cancelBtn.Clicked(gtx) {
		d.Visible = false

		if d.OnCancel != nil {
			d.OnCancel()
		}
	}

	if !d.Visible {
		return layout.Dimensions{}
	}

	var overlay widget.Clickable

	return layout.Stack{}.Layout(gtx,
		layout.Expanded(func(gtx layout.Context) layout.Dimensions {
			return overlay.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
				size := gtx.Constraints.Max
				paint.FillShape(gtx.Ops, color.NRGBA{A: 80}, clip.Rect{Max: size}.Op())
				return layout.Dimensions{Size: size}
			})
		}),
		layout.Stacked(func(gtx layout.Context) layout.Dimensions {
			return layout.Inset{Top: unit.Dp(100), Bottom: unit.Dp(100), Left: unit.Dp(200), Right: unit.Dp(200)}.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
				paint.FillShape(gtx.Ops, color.NRGBA{R: 255, G: 255, B: 255, A: 255},
					clip.RRect{
						Rect: image.Rectangle{Max: gtx.Constraints.Max},
						SE:   10,
						SW:   10,
						NW:   10,
						NE:   10,
					}.Op(gtx.Ops))
				return widget.Border{
					Color:        color.NRGBA{A: 100},
					CornerRadius: 5,
					Width:        1,
				}.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
					return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
						layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
							return layout.Flex{Axis: layout.Horizontal, Alignment: layout.Middle}.Layout(gtx,
								layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
									return layout.Center.Layout(gtx, func(gtx layout.Context) layout.Dimensions {
										spacer := layout.Rigid(layout.Spacer{Height: unit.Dp(30)}.Layout)
										return layout.Flex{Axis: layout.Vertical}.Layout(gtx,
											spacer,
											layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
												return material.H6(d.titleTh, d.Title).Layout(gtx)
											}),
											layout.Flexed(1, func(gtx layout.Context) layout.Dimensions {
												return material.Body1(d.messageTh, d.Message).Layout(gtx)
											}),
											layout.Rigid(func(gtx layout.Context) layout.Dimensions {
												children := []layout.FlexChild{}

												if d.ConfirmVisible {
													children = append(children, layout.Rigid(func(gtx layout.Context) layout.Dimensions {
														return material.Button(d.th, &d.confirmBtn, d.ConfirmText).Layout(gtx)
													}))
												}

												if d.Type == Confirm && d.CancelVisible {
													children = append(children, layout.Rigid(layout.Spacer{Width: unit.Dp(30)}.Layout))
													children = append(children, layout.Rigid(func(gtx layout.Context) layout.Dimensions {
														return material.Button(d.th, &d.cancelBtn, d.CancelText).Layout(gtx)
													}))
												}
												return layout.Flex{Axis: layout.Horizontal}.Layout(gtx, children...)
											}),
											spacer)
									})
								}))
						}))
				})
			})
		}),
	)
}
